<template>
  <div class="flex flex-col gap-4">
    <div class="flex gap-2 items-center">
      <div class="w-20">模型名称</div>
      <el-input v-model="test" placeholder="请输入文件名"></el-input>
    </div>
    <div class="flex gap-2 items-center">
      <div class="w-20">备注</div>
      <el-input v-model="test" placeholder=""></el-input>
    </div>
    <div class="flex gap-2 items-center">
      <div class="w-20">上传模型</div>
      <input type="file" name="file" id="fileinput" @change="fileUploadChanged" :multiple="false" style="display: none" />
      <el-button
        v-loading="loading"
        @click="fileButtonClick()"
        :disabled="!isUploadClick"
        icon="el-icon-upload"
        size="mini"
        plain
        style='width"96px;height:38px;font-size: 14px;'
      >
        {{ fileButtonText }}
      </el-button>
      <div class="currentfilename" v-if="!isAutoUpload">{{ waitUploadFile }}</div>
      <el-button @click="fileUploadStartup" v-show="isFileUploadStartupBottonShow" v-if="!isAutoUpload" size="mini" plain
        >点击上传
      </el-button>
    </div>
    <div v-show="currentFileName.length > 0">
      <div class="fileuploadgroup" v-for="(item, index) in currentFileName" :key="index">
        <div class="currentfilename" @click="handleFileDownloadClick(item)">{{ item.name }}</div>
        <el-progress
          :text-inside="true"
          :stroke-width="18"
          v-if="percentage"
          :percentage="percentage"
          class="elprogress"
          v-show="isProgressVis && index === currentFileName.length - 1"
        ></el-progress>
        <i
          class="el-icon-delete"
          title="删除文件"
          @click="handleFileDelClick(item)"
          v-show="isDeleteIconShow && (!isProgressVis || index != currentFileName.length - 1)"
          :style="{ cursor: 'pointer' }"
        ></i>
      </div>
    </div>
  </div>
</template>
<script>
import * as CryptoJS from 'crypto-js'
import { initUpload, uploadChunk, mergeFile } from '@/api/bigfileupload'

export default {
  name: 'bigFileUpload',
  data() {
    return {
      percentage: 0,
      filesdata: [],
      // 遮罩层
      loading: false,
      isDeleteIconShow: false,
      isFileUploadStartupBottonShow: false,
      isProgressVis: false,
      currentFileName: [],
      waitUploadFile: '',
      isUploadClick: true,
      // 大文件上传相关信息
      uploadId: '',
      //   md5Str: '',
      // 上传成功后文件地址
      fileUrl: '',
      // 上传文件块号
      chunkId: 0,
      md5Str: []
    }
  },
  props: {
    // 上传方式：true - 自动上传；false - 手动上传
    isAutoUpload: {
      type: Boolean,
      default: false
    },
    // 单/多文件：true - 多文件；false - 单文件
    isMultiple: {
      type: Boolean,
      default: false
    },
    // 景区代码
    scenicId: {
      type: Number,
      default: null
    }
  },
  computed: {
    fileButtonText() {
      if (this.currentFileName.length === 0) {
        return '上传文件'
      } else {
        return '继续添加'
      }
    }
  },
  created() {
    if (!this.histFileArr) {
      this.isDeleteIconShow = false
      this.currentFileName = []
      return
    }
    this.isDeleteIconShow = true
    this.currentFileName = this.histFileArr
  },
  methods: {
    fileUploadChanged() {
      this.filesdata = this.$el.getElementsByTagName('input')[0].files // this.$el.getElementsByTagName方法可返回带有指定标签名的对象的集合。
      console.log(this.filesdata, 'this.filesdata')
      if (this.filesdata.length === 0) return
      this.isDeleteIconShow = true
      this.isFileUploadStartupBottonShow = true
      this.isProgressVis = false
      this.percentage = 0
      this.waitUploadFile = this.filesdata[0].name
      if (this.isAutoUpload) {
        this.fileUploadStartup()
      }
    },
    fileUploadStartup() {
      this.loading = true
      this.isUploadClick = false
      this.isDeleteIconShow = false
      this.isFileUploadStartupBottonShow = false
      // 初始化参数
      this._name = this.filesdata[0].name // 文件名
      this._size = this.filesdata[0].size // 总大小
      this._shardSize = 4 * 1024 * 1024 // 以2MB为一个分片
      this._shardCount = Math.ceil(this._size / this._shardSize) // 总片数
      this.uploaded = 0

      if (!this.isMultiple) {
        this.fileDelOper(this.currentFileName[0]) // 进行删除操作
        this.currentFileName = []
      }
      this.isProgressVis = true
      this.currentFileName.push({ name: this.filesdata[0].name })
      // 初始化大文件上传，传入景区代码文文件名，返回uploadId
      const self = this
      console.log(this.filesdata, '=======')

      initUpload({
        fileName: this.filesdata[0].name,
        fileDesc: '文件描述测试',
        workspaceId: 'e3dea0f5-37f2-4d79-ae58-490af3228069'
      }).then((response) => {
        console.log(response)
        if (response.code === 1) {
          //   self.msgSuccess('大文件上传初始化成功')
          // 从第0块开始上传
          self.uploadId = response.data.uploadId
          self.uploadByChunk(self.chunkId)
        } else {
          self.msgError(response.msg)
        }
      })
    },
    // 分片上传大文件
    uploadByChunk(index) {
      this._start = index * this._shardSize
      this._end = Math.min(this._size, this._start + this._shardSize) // 结束时总大小，和 开始的大小+之前的大小比较
      const self = this
      const fileData = this.filesdata[0].slice(this._start, this._end)
      // 获取文件块MD5
      console.log(fileData, 'fileData', this._start, this._end)
      const reader = new FileReader()
      reader.readAsArrayBuffer(fileData)
      // 读取成功后的回调
      reader.onloadend = function () {
        console.log(this.result, '生成的md数据')
        // 将ArrayBuffer转换为WordArray
        const wordArray = CryptoJS.lib.WordArray.create(this.result)
        console.log(wordArray, '生成的WordArray数据')
        // 用hex_md5生成md5值，与OSS的算法对应，并转换为大写，不是直接md5-js的算法
        self.md5Str[index] = CryptoJS.MD5(wordArray).toString().toUpperCase()
        console.log(self.md5Str[index])
      }
      const form1 = new FormData() // new一个form的实例，可以进行键值对的添加，
      form1.append('chunkFile', fileData) // slice方法用于切出文件的一部分
      form1.append('uploadId', this.uploadId)
      form1.append('chunkId', (index + 1).toString())
      form1.append('total', this._shardCount.toString()) // 是否最后一片
      uploadChunk(form1).then((response) => {
        console.log(response.data.md5Str, self.md5Str)
        if (response.code === 1) {
          // 判断返回的MD5值是否一致，一致继续传下一块，否则重传本块
          if (self.md5Str[index] === response.data.md5Str) {
            console.log('第' + (index + 1).toString() + '块文件上传成功')
            self.uploaded++
            const percent = Math.floor((self.uploaded / self._shardCount) * 100)
            self.percentageSend(percent)
            // 如果没上传完成，继续上传一下块
            index++
            if (index < self._shardCount) {
              this.uploadByChunk(index)
            }
          } else {
            console.log('第' + (index + 1).toString() + '块文件上传不成功，重新上传')
            // 不一致，重新传本块
            // this.msgSuccess('第' + (index + 1).toString() + '块文件上传不成功，重新上传')
            this.uploadByChunk(index)
          }
        } else {
          // 出错，跳出循环显示错误
          this.msgError(response.msg)
        }
      })
    },
    // 接收上传的百分值回调
    percentageSend(perNum) {
      this.percentage = perNum
      // 如果上传完成，合并文件
      if (perNum === 100) {
        const form2 = new FormData() // new一个form的实例，可以进行键值对的添加，
        form2.append('uploadId', this.uploadId)
        mergeFile(this.uploadId).then((response) => {
          console.log(response)
          if (response.code === 200) {
            this.msgSuccess('大文件合并成功')
            this.fileUrl = response.url
            this.successUpload(true, this.filesdata[0], response.url)
          } else {
            this.msgError(response.msg)
          }
        })
        this.loading = false
      }
    },
    successUpload(success, field, value) {
      if (success) {
        if (this.percentage < 100) return
        this.isDeleteIconShow = true
        this.isFileUploadStartupBottonShow = false
        this.isProgressVis = false
        this.isUploadClick = true
        document.getElementById('fileinput').value = ''
        this.waitUploadFile = ''
        this.successvalue = value
        console.log(this.successvalue)
        this.$emit('successvalue', this.successvalue)
        this.$message({
          message: '文件上传成功',
          type: 'success'
        })
      }
    },
    // 点击文件后面的删除按钮
    handleFileDelClick(item) {
      this.filesdata = []
      document.getElementById('fileinput').value = ''
      for (let i = 0; i < this.currentFileName.length; i++) {
        if (this.currentFileName[i].name === item.name) {
          this.fileDelOper(item) // 进行删除操作
          this.currentFileName.splice(i, 1) // 删除下标为i的元素
          return this.currentFileName
        }
      }
      this.isDeleteIconShow = false
      this.isFileUploadStartupBottonShow = false
      this.isProgressVis = false
    },
    // 点击选取文件
    fileButtonClick() {
      document.getElementById('fileinput').click()
    },
    // 删除操作
    fileDelOper(val) {
      this.$emit('fileDelOper', val)
    },
    // 点击文件下载
    handleFileDownloadClick(val) {
      this.$emit('fileDownload', val)
    }
  }
}
</script>

<style scoped>
a {
  color: #65b978;
}
</style>
